package com.ruoyi.equip.vert.service.impl;

import com.github.yitter.idgen.YitIdHelper;
import com.ruoyi.common.utils.JsonUtils;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.common.utils.net.HexUtil;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.equip.domain.ProbeData;
import com.ruoyi.equip.domain.TagData;
import com.ruoyi.equip.domain.cache.DeviceTagCache;
import com.ruoyi.equip.domain.cache.TagCache;
import com.ruoyi.equip.mapper.ProbeDataMapper;
import com.ruoyi.equip.mapper.TagDataMapper;
import com.ruoyi.equip.util.CacheUtils;
import com.ruoyi.equip.util.ModelCacheUtils;
import com.ruoyi.equip.vert.domain.TcpParserEntity;
import com.ruoyi.equip.vert.domain.param.TagDataEntity;
import com.ruoyi.equip.vert.service.TransferStrategy;
import com.ruoyi.td.entity.DevicePropertyCache;
import com.ruoyi.td.service.IDeviceInfoData;
import com.ruoyi.td.service.IDevicePropertyData;
import com.ruoyi.td.vo.ThingModelVo;
import lombok.extern.slf4j.Slf4j;
import org.checkerframework.checker.units.qual.A;
import org.checkerframework.checker.units.qual.C;
import org.checkerframework.checker.units.qual.K;
import org.springframework.security.core.parameters.P;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;

import static com.ruoyi.equip.util.HeartCacheUtils.setOnline;
import static com.ruoyi.equip.vert.TcpReaderConstant.DATA_SUCCESS;

@Slf4j
@Service
public class DataTransfer implements TransferStrategy
{

    private IDevicePropertyData devicePropertyData = SpringUtils.getBean(IDevicePropertyData.class);


    //private IDeviceInfoData deviceInfoData = SpringUtils.getBean(IDeviceInfoData.class);


    TagDataMapper tagDataMapper = SpringUtils.getBean(TagDataMapper.class);

    ProbeDataMapper probeDataMapper = SpringUtils.getBean(ProbeDataMapper.class);

    public static HashMap<String, Map<String, DevicePropertyCache>> realData = new HashMap<>();

    @Override
    public void transfer(TcpParserEntity tcpParserEntity)
    {
        String readerId = tcpParserEntity.getReaderId();
        //readerId = "00000001";
        List<String> param = tcpParserEntity.getParam();

        if (param.get(param.size() - 3).equals("01") && param.get(param.size() - 2).equals("00") && param.get(param.size() - 1).equals("00")) {
            log.error("数据异常");
            return;
        }
        // 解析数据
        int curPos = 0;
        String optResult = param.get(curPos++);
        String readResult = param.get(curPos++);

        if (StringUtils.equals(optResult, DATA_SUCCESS)) {
            //if (StringUtils.equals(optResult, DATA_SUCCESS) && StringUtils.equals(readResult, DATA_SUCCESS)) {
            String ant = param.get(curPos++);
            //todo temp
            curPos = curPos + 4;
            int tagLen = HexUtil.hexStrToInt(param.get(curPos++));
            String tagId = HexUtil.hexListToStr(param, curPos, curPos + tagLen);
            curPos += tagLen;
            String tagType = param.get(curPos++);
            //int dataLen = HexUtil.hexStrToInt(param.get(curPos++));
            String data = HexUtil.hexListToStr(param, curPos, curPos + 2);

            TagDataEntity tagDataEntity = new TagDataEntity();
            tagDataEntity.setReaderId(readerId);
            tagDataEntity.setTagId(tagId);
            tagDataEntity.setTagType(tagType);
            tagDataEntity.setAnt(ant);
            tagDataEntity.setData(data);
            dataComputed(tagDataEntity);


        }
    }

    public void dataComputed(TagDataEntity tagDataEntity)
    {
        Date date = new Date();
        Long occurred = System.currentTimeMillis();
        String readerId = tagDataEntity.getReaderId();
        String tagSbId = tagDataEntity.getTagId();
        String data = tagDataEntity.getData();
        DeviceTagCache deviceTagCache = CacheUtils.getDeviceTagCache(readerId);
        String deviceId = deviceTagCache.getDeviceId();
        String productKey = deviceTagCache.getProductKey();
        TagCache tagCache = deviceTagCache.getTags().get(tagSbId);
        if (tagCache.getState() == 0) {
            log.info("该标签已被闲置,数据不给予记录-tagSbId:{}", tagSbId);
            return;
        }
        String tagId = tagCache.getTagId();
        String tagCacheProductKey = tagCache.getProductKey();
        Map<String, DevicePropertyCache> addProperties = new HashMap<>();
        Map<String, ThingModelVo.Property> modelCache = ModelCacheUtils.getModelCache(tagCacheProductKey);

        // 进行手动数据转换
        String tagType = tagDataEntity.getTagType().toLowerCase();
        //if (tagType.equals("00")) {
        // tmp 00
        TagData tagData = new TagData();
        ProbeData probeData = null;
        if (tagType.equals("01")) {
            if (modelCache.containsKey("tempature")) {
                ThingModelVo.Property model = JsonUtils.parseObject(JsonUtils.toJsonString(modelCache.get("tempature")), ThingModelVo.Property.class);
                String name = model.getName();
                String unit = model.getUnit();
                // 温度类型
                Double IntegerPart = (Integer.parseInt(data.substring(0, 2), 16) - 60) * 1.0;
                int pointPart = Integer.parseInt(data.substring(2, 4), 16);
                String tempature = String.format("%.1f", (IntegerPart + pointPart * 1.0 / 256));
                DevicePropertyCache propertyCache = new DevicePropertyCache();
                propertyCache.setValue(Double.valueOf(tempature));
                propertyCache.setOccurred(occurred);
                propertyCache.setName(name);
                propertyCache.setUnit(unit);
                tagData.setReportTime(occurred);
                tagData.setTagId(tagId);
                tagData.setData(Double.valueOf(tempature));
                if (Double.valueOf(tempature) > tagCache.getMax()) {
                    probeData = new ProbeData(YitIdHelper.nextId(), deviceTagCache.getDeviceId(), tagId, tagSbId, 1, tempature, 2, "高温", date, deviceTagCache.getDeptId(), deviceTagCache.getUserId());
                } else if (Double.valueOf(tempature) < tagCache.getMin()) {
                    probeData = new ProbeData(YitIdHelper.nextId(), deviceTagCache.getDeviceId(), tagId, tagSbId, 1, tempature, 1, "低温", date, deviceTagCache.getDeptId(), deviceTagCache.getUserId());
                }
                addProperties.put("tempature", propertyCache);
            }

        } else if (tagType.equals("f0")) {
            if (modelCache.containsKey("pressure")) {
                ThingModelVo.Property model = JsonUtils.parseObject(JsonUtils.toJsonString(modelCache.get("pressure")), ThingModelVo.Property.class);
                String name = model.getName();
                String unit = model.getUnit();
                // 压力类型
                Double IntegerPart = (Integer.parseInt(data.substring(0, 2), 16) - 60) * 1.0;
                int pointPart = Integer.parseInt(data.substring(2, 4), 16);
                String pressure = String.format("%.1f", (IntegerPart + pointPart * 1.0 / 256));
                DevicePropertyCache propertyCache = new DevicePropertyCache();
                propertyCache.setValue(Double.valueOf(pressure));
                propertyCache.setOccurred(occurred);
                propertyCache.setName(name);
                propertyCache.setUnit(unit);
                addProperties.put("pressure", propertyCache);
            }

        } else if (tagType.equals("89")) {
            // 温湿度
            if (modelCache.containsKey("tempature")) {
                ThingModelVo.Property model = JsonUtils.parseObject(JsonUtils.toJsonString(modelCache.get("tempature")), ThingModelVo.Property.class);
                String name = model.getName();
                String unit = model.getUnit();
                Double IntegerPart1 = (Integer.parseInt(data.substring(0, 2), 16) - 60) * 1.0;
                int pointPart1 = Integer.parseInt(data.substring(2, 4), 16);
                String tempature = String.format("%.1f", (IntegerPart1 + pointPart1 * 1.0 / 256));
                DevicePropertyCache propertyCache = new DevicePropertyCache();
                propertyCache.setValue(Double.valueOf(tempature));
                propertyCache.setOccurred(occurred);
                propertyCache.setName(name);
                propertyCache.setUnit(unit);
                addProperties.put("tempature", propertyCache);
            }
            if (modelCache.containsKey("humidity")) {
                ThingModelVo.Property model = JsonUtils.parseObject(JsonUtils.toJsonString(modelCache.get("humidity")), ThingModelVo.Property.class);
                String name = model.getName();
                String unit = model.getUnit();
                Double IntegerPart2 = (Integer.parseInt(data.substring(4, 6), 16) - 60) * 1.0;
                int pointPart2 = Integer.parseInt(data.substring(6, 8), 16);
                String humidity = String.format("%.1f", (IntegerPart2 + pointPart2 * 1.0 / 256));
                DevicePropertyCache propertyCache = new DevicePropertyCache();
                propertyCache.setValue(Double.valueOf(humidity));
                propertyCache.setOccurred(occurred);
                propertyCache.setName(name);
                propertyCache.setUnit(unit);
                addProperties.put("humidity", propertyCache);
            }

        } else {
            log.info("错误数据类型,数据进行抛弃");
        }
        //设置在线缓存
        setOnline(deviceId, productKey);
        setOnline(tagId, tagCacheProductKey);
        //
        // 进行数据缓存
        //updateDeviceCurrentProperties(tagId, addProperties);
        realData.put(tagId, addProperties);
        tagDataMapper.insert(tagData);
        if (probeData != null) {

            probeData.setDeviceId(deviceId);
            probeDataMapper.insert(probeData);
        }
        //devicePropertyData.addProperties(tagId, tagCacheProductKey, addProperties, occurred);
    }


    //public ThingModelVo.Property getPropertyDetail(String key, Map<String, ThingModelVo.Property> modelCache) {
    //    return JsonUtils.parseObject(JsonUtils.toJsonString(modelCache.get(key)), ThingModelVo.Property.class);
    //}

    /**
     * 更新设备当前属性
     */
    //private void updateDeviceCurrentProperties(String deviceId, Map<String, DevicePropertyCache> properties) {
    //    try {
    //        log.info("save device property,deviceId:{},property:{}", deviceId, JsonUtils.toJsonString(properties));
    //        deviceInfoData.saveProperties(deviceId, properties);
    //    } catch (Throwable e) {
    //        log.error("save device current properties error", e);
    //    }
    //}


}
